package net.zoneland.knowledge.controller;

import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.io.resource.InputStreamResource;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.builder.ExcelReaderBuilder;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.github.pagehelper.PageInfo;
import com.google.common.base.Preconditions;
import io.swagger.models.HttpMethod;
import lombok.SneakyThrows;
import net.zoneland.knowledge.config.MeetingConfig;
import net.zoneland.knowledge.constant.Constants;
import net.zoneland.knowledge.enums.SecretaryProjectFormExcelEnum;
import net.zoneland.knowledge.exceptions.MeetingQrException;
import net.zoneland.knowledge.exceptions.UserServiceException;
import net.zoneland.knowledge.model.*;
import net.zoneland.knowledge.model.security.OperationContextHolder;
import net.zoneland.knowledge.service.MeetingQrService;
import net.zoneland.knowledge.service.MeetingSignInService;
import net.zoneland.knowledge.utils.DateHelper;
import net.zoneland.knowledge.utils.ExcelUtils;
import net.zoneland.knowledge.utils.HttpClientUtils;
import net.zoneland.knowledge.utils.LoginUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import static net.zoneland.knowledge.constant.Constants.MEETING_ID;
import static net.zoneland.knowledge.constant.Constants.URGING_TYPE;

/**
 * 会议相关控制层.
 * @author chw.
 * @version V1.0
 * 2022-11-18
 */
@Controller
@RequestMapping("/meeting")
public class MeetingController extends AbstractBaseController {

    /**
     * LOG.
     */
    private static final Logger LOG = LoggerFactory.getLogger(MeetingController.class);

    /**
     * 会议签到接口.
     */
    @Autowired
    private MeetingSignInService meetingSignInService;

    /**
     * 会议(二维码)接口.
     */
    @Autowired
    private MeetingQrService meetingQrService;

    /**
     * 会议手动催办链接.
     */
    @Autowired
    private MeetingConfig meetingConfig;

    /**
     * 签到结果显示页面.
     */
    private static final String SIGN_IN_JSP = "forward:/meetingSignIn.jsp";

    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateHelper.DATE_PATTERN);

    /**
     * 会议签到.
     * @param id 会议id
     * @param modelAndView modelAndView
     * @return 返回成功或失败页面
     */
    @GetMapping("/signIn.htm")
    public ModelAndView signIn(@RequestParam("id") final String id, final ModelAndView modelAndView)  {
        final String token = (String) OperationContextHolder.getPrincipal().getAttrMap().get(Constants.TOKEN_NAME);
        final LoginUserPojo loginUserPojo = LoginUtils.getCurrentUserByToken(token);
        Preconditions.checkNotNull(loginUserPojo, "会议签到,获取登录信息失败!");

        LOG.info("会议签到,获取人员登录信息成功 用户id = {}", loginUserPojo.getUserID());
        final ResponseResult responseResult = meetingSignInService.doSignIn(id, loginUserPojo);
        modelAndView.addObject("result", responseResult.getResult());
        modelAndView.addObject("meetingSignIn", responseResult.getData());
        if (Objects.nonNull(responseResult.getData())) {
            final MeetingSignIn signIn = (MeetingSignIn) responseResult.getData();
            modelAndView.addObject("signInDate", signIn.getSignInDate().format(formatter));
        }
        modelAndView.addObject("message", responseResult.getMessage());
        modelAndView.setViewName(SIGN_IN_JSP);
        return modelAndView;
    }

    /**
     * 获取有会议的天数，用于在日历上显示.
     * @param request 请求
     * @return ResponseResult data为[yyyy-mm-dd]日期列表
     */
    @ResponseBody
    @GetMapping("/findMeetingDatesByUserId")
    public ResponseResult<List<MeetingQr>> findWorkSubTasksByUserId(final HttpServletRequest request) {
        final ResponseResult res = new ResponseResult();
        final LoginUserPojo user = getAndCheckCurrentUser(request);

        res.setData(meetingSignInService.findNotFinishMeetingDateByUserId(user.getUserID()));

        return res;
    }

    /**
     * 软删除会议
     * @param meetingQr 会议二维码实体类
     * @return 统一返回结果集
     */
    @ResponseBody
    @PostMapping("/edit-meeting-status")
    public ResponseResult editMeetingStatus(final @RequestBody MeetingQr meetingQr) {
        meetingQrService.editMeetingQrStatus(meetingQr);
        return new ResponseResult("删除成功", DateHelper.getLocalDateTime(LocalDateTime.now()), "");
    }

    /**
     * 根据创建人id查询创建的会议
     * @param meetingQr 会议二维码实体类
     * @return
     */
    @ResponseBody
    @GetMapping("/query-meeting-by-createid")
    public ResponseResult queryMeetingByCreateId(final MeetingQr meetingQr) {
        final List<MeetingQr> result = meetingQrService.queryMeetingByCreateId(meetingQr.getCreatorId());
        return new ResponseResult("查询成功", DateHelper.getLocalDateTime(LocalDateTime.now()), result);
    }

    /**
     * 根据oaId查询我参加的会议
     * @param meetingSignIn 会议签到实体类.
     * @return
     */
    @ResponseBody
    @GetMapping("/query-join-meeting-by-oaid")
    public ResponseResult queryJoinMeetingByOaId(final MeetingSignIn meetingSignIn) {
        final List<MeetingQr> result = meetingSignInService.queryJoinMeetingByOaId(meetingSignIn);
        return new ResponseResult("成功查询我参加的会议", DateHelper.getLocalDateTime(LocalDateTime.now()), result);
    }


    /**
     * 查询参会二维码
     * @param meetingQr 会议(二维码).
     * @return
     */
    @ResponseBody
    @GetMapping("/query-meeting-code")
    public ResponseResult queryMeetingCode(final MeetingQr meetingQr) {
        if (StringUtils.isBlank(meetingQr.getId())) {
            return new ResponseResult("id为空", DateHelper.getDateTime(new Date()), null);
        }
        final MeetingQr meetingQrCode = meetingQrService.queryMeetingQrCode(meetingQr.getId());
        return new ResponseResult("参会二维码查询成功",DateHelper.getLocalDateTime(LocalDateTime.now()), meetingQrCode);
    }


    /**
     * 会议详情
     * @param meetingQr 会议(二维码).
     * @return
     */
    @ResponseBody
    @GetMapping("/query-meeting-content")
    public ResponseResult queryMeetingContent(final MeetingQr meetingQr) {
        final MeetingQr content = meetingQrService.queryMeetingContent(meetingQr.getId());
        return new ResponseResult("会议详情查询成功", DateHelper.getLocalDateTime(LocalDateTime.now()), content);
    }

    /**
     * 参会人员详情.
     * @return
     */
    @ResponseBody
    @PostMapping("/query-sign-in-user-by-meetingid")
    public ResponseResult querySignInUserByMeetingId(final @RequestBody MeetingSignIn meetingSignIn) {
        final List<MeetingSignIn> signInParam = meetingSignInService.querySignInUserByMeetingId(meetingSignIn.getMeetingId());
        return new ResponseResult("参会人员详情查询成功", DateHelper.getLocalDateTime(LocalDateTime.now()), signInParam);
    }

    /**
     * 新增 编辑会议信息.
     * @param meetingQr 会议信息
     * @return 会议信息
     */
    @ResponseBody
    @PostMapping("/save-meeting")
    public ResponseResult saveMeeting(final HttpServletRequest request, final @RequestBody MeetingQr meetingQr)  {
        final String token = request.getHeader(Constants.TOKEN_NAME);
        final LoginUserPojo loginUserPojo = LoginUtils.getCurrentUserByToken(token);
        return new ResponseResult("保存成功", DateHelper.getLocalDateTime(LocalDateTime.now()), meetingQrService.saveMeeting(meetingQr, loginUserPojo));
    }

    /**
     * 保存参会人员
     * @param meetingSignIns 参会人员信息
     * @return
     * @throws IOException
     */
    @ResponseBody
    @PostMapping( "/save-meeting-attendee")
    public ResponseResult saveMeetingAttendee(@RequestBody final List<MeetingSignIn> meetingSignIns) {
        meetingQrService.saveMeetingAttendee(meetingSignIns);
        return new ResponseResult("保存成功");
    }

    /**
     * 删除参会人员.
     * @return
     */
    @ResponseBody
    @GetMapping( "/delete-sign-in-userid")
    public ResponseResult deleteSignInUserId(@RequestParam("id") final String id, @RequestParam("meetingid") final String meetingId) {
        if (StringUtils.isAnyBlank(id, meetingId)) {
            return new ResponseResult("请求参数缺失，删除失败");
        }
        meetingQrService.deleteSignInfo(id);
        meetingQrService.deleteImportCountNum(meetingId);
        return new ResponseResult("删除成功");
    }

    /**
     * 会议二维码分页数据
     * @param currPage 当前页
     * @param pageSize 每页记录数
     * @param creatorId 创建人
     * @param meetingTitle 会议标题
     * @return
     */
    @ResponseBody
    @GetMapping( "/query-meeting-pager")
    public ResponseResult queryMeetingPager(final @RequestParam("currpage") Integer currPage,
                                            final @RequestParam("pagesize") Integer pageSize,
                                            final @RequestParam("creatorid") String creatorId,
                                            final @RequestParam("meetingtitle") String meetingTitle) {
        try {
            final MeetingQr meetingQr = new MeetingQr();
            meetingQr.setMeetingTitle(meetingTitle);
            meetingQr.setCreatorId(creatorId);
            final PageInfo<MeetingQr> meetingPage = meetingQrService.queryPager(currPage, pageSize, meetingQr);
            return new ResponseResult<>("查询会议二维码数据成功", DateHelper.getLocalDateTime(LocalDateTime.now()), meetingPage);
        } catch (final MeetingQrException e) {
            LOG.error("会议二维码数据查询失败，currPage: {}, pageSize: {}, creatorId: {}, errorMessage: {}", currPage, pageSize, creatorId, e.getMessage());
            return new ResponseResult<>("会议二维码数据查询失败", DateHelper.getLocalDateTime(LocalDateTime.now()), null);
        }
    }

    /**
     * 会议信息excel导入
     * @param file excel文件
     * @param meetingId 会议id
     * @return
     * @throws IOException
     */
    @ResponseBody
    @PostMapping( "/upload-excel")
    public ResponseResult uploadExcel(final @RequestParam("file") MultipartFile file, final @RequestParam("meetingid") String meetingId) throws IOException {

        return meetingSignInService.meetingUpload(file, meetingId);
    }

    /**
     * 批量删除签到人员
     * @param ids
     * @return
     */
    @ResponseBody
    @GetMapping("/batch-delete")
    public ResponseResult batchDelete(final @RequestParam("ids") String ids, final @RequestParam("meetingid") String meetingId) {
        final int deleteNum = meetingSignInService.batchDeleteById(ids, meetingId);
        return new ResponseResult("删除成功", DateHelper.getLocalDateTime(LocalDateTime.now()), String.valueOf(deleteNum));
    }

    /**
     * 手动催办
     * @param meetingId 会议id
     * @param urgingType 催办类型
     * @return
     */
    @SneakyThrows
    @ResponseBody
    @GetMapping("/urge-handle")
    public ResponseResult urgeHandle (final @RequestParam("meetingid") String meetingId,
                                      final @RequestParam("urgingtype") String urgingType) {
        final HashMap<String, String> headMap = new HashMap<>();
        headMap.put(MEETING_ID, meetingId);
        headMap.put(URGING_TYPE, urgingType);
        HttpClientUtils.doGet(String.format(meetingConfig.getMeetingUrgeUrl(), meetingId, urgingType), new HashMap<>());
        return new ResponseResult("催办成功");
    }

    /**
     * 会议excel模板下载
     * @param response http响应
     */
    @GetMapping("/download-meeting-excel")
    public void downloadMeetingExcel(final HttpServletResponse response) {
        try (final InputStream classInputStream = ChapterApplyInfoController.class.getResourceAsStream(
                "/excelTemplate/meetingAttendeeTemplate.xlsx")) {
            response.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + URLEncoder.encode("参会人员导入模板.xlsx", "UTF-8"));
            IOUtils.copy(classInputStream, response.getOutputStream());
            response.flushBuffer();
        } catch (final IOException e) {
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }
}
